import moment from "moment";
import { userStore } from "@/pinia/user";
import Compressor from "compressorjs";
import { v4 as uuidv4 } from "uuid";

/**
 * @description: 格式化dataV的单元格信息，可定义颜色以及是否加宽
 * @param {*} text：文字内容
 * @param {*} color：颜色，默认为白色
 * @param {*} isFontWeight：是否字体是否加宽
 */
export function formatHeaderData(text, color = "#fff", isFontWeight) {
  return `<span style="color:${color};font-weight: 700;">${text}</span>`;
}

/**
 * @description: 对象数组筛选
 * @param {*} obj：数据源
 * @param {*} key：筛选的key，需要筛选的键值
 * @param {*} label：返回对象键的key，默认：label
 * @param {*} value：返回对象值的key，默认：value
 * @return {*} [{lable:xxx,value:xxx}]
 */
export function _objArrFilter(obj, key, label = "label", value = "value") {
  let data = [];
  data = obj.reduce((acc, pre) => {
    const result = acc.find((item) => item.value === pre[key]);
    if (!result) {
      let _data = {};
      _data[label] = pre[key];
      _data[value] = pre[key];
      acc.push(_data);
    }
    return acc;
  }, []);

  return data;
}

/**
 * @description: 对象数组中，相同的key求和
 * @param {*} data：数据源
 * @param {*} key：指定的key
 * @return {*}：求和结果
 */
export function alikeKeyGetAll(data = [], key) {
  const result = data.reduce((acc, pre) => {
    acc += pre[key];
    return acc;
  }, 0);
  return result;
}

/**
 * @description: echart根据界面变化调整文字大小
 * @param {*} res：文字大小，标题：0.16 图例、图表：0.14
 * @return {*} 当前屏幕下的文字大小
 */
export function fontSize(res) {
  let clientWidth =
    window.innerWidth ||
    document.documentElement.clientWidth ||
    document.body.clientWidth;

  if (!clientWidth) return;
  let fontSize = 100 * (clientWidth / 1920);
  return res * fontSize;
}

/**
 * @description: 格式化金额
 * @param {*} money：数字或字符串，如：12123
 * @return {*}：1,2123
 */
export function formatMoney(number1, number, length = 2) {
  // 原始值
  let originalValue, respnonseValue;

  if (number1 === null) {
    originalValue = number;
    length = length;
  } else {
    originalValue = number1;
    length = number ? length : 2;
  }

  originalValue = parseFloat(originalValue);

  if (isNaN(originalValue)) {
    respnonseValue = 0;
  } else {
    respnonseValue = originalValue
      .toFixed(length)
      .replace(/(\d)(?=(\d{3})+\.)/g, "$1,");

    // 如果第一个参数是null 就表示需要对结果进行格式化 示例： "123.00" => "123"  "789.0" => "789"
    if (number1 === null) respnonseValue = respnonseValue.replace(/\.0+$/, "");
  }

  return respnonseValue;
}

/**
 * @description: 生成随机色
 * @return {*}：#ffffff
 */
export function getRandomColor() {
  // const colors = ['#ff461f', '#ff2d51', '#3eede7', '#ffa400', '#00bc12', '#fcefe8', '#0eb83a', '#f20c00', '#c0ebd7', '#00e500', '#2add9c', '#3de1ad', '#ff0097', '#008b8b', '#ff2121', '#8d4bbb', '#f47983', '#ff7500', '#e4c6d0']

  // const rand = Math.floor(Math.random() * (colors.length - 0 + 1)) + 0

  var letters = "0123456789ABCDEF";
  var color = "#";
  for (var i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}

/**
 * @description: 快捷时间：一周、一个月、三个月、六个月、一年
 * @return {*}
 */
export function defaultShortcuts() {
  return [
    {
      text: "今天",
      value: () => {
        const end = new Date();
        const start = new Date();
        //   start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
        return [start, end];
      },
    },
    {
      text: "一周",
      value: () => {
        const end = new Date();
        const start = new Date();
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
        return [start, end];
      },
    },
    {
      text: "一个月",
      value: () => {
        const end = new Date();
        const start = new Date();
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
        return [start, end];
      },
    },
    {
      text: "三个月",
      value: () => {
        const end = new Date();
        const start = new Date();
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
        return [start, end];
      },
    },
    {
      text: "六个月",
      value: () => {
        const end = new Date();
        const start = new Date();
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 30 * 6);
        return [start, end];
      },
    },
    {
      text: "一年",
      value: () => {
        const end = new Date();
        const start = new Date();
        start.setTime(start.getTime() - 3600 * 1000 * 24 * 30 * 12);
        return [start, end];
      },
    },
  ];
}

/**
 * @description: 快捷选择目标日期
 * @return {*}
 */
export function shortcutsEndDate() {
  return [
    {
      text: "明天",
      value: () => {
        const date = new Date();
        date.setTime(date.getTime() + 3600 * 1000 * 24);
        return date;
      },
    },
    {
      text: "一个月",
      value: () => {
        const date = new Date();
        date.setTime(date.getTime() + 3600 * 1000 * 24 * 30);
        return date;
      },
    },
    {
      text: "三个月",
      value: () => {
        const date = new Date();
        date.setTime(date.getTime() + 3600 * 1000 * 24 * 30 * 3);
        return date;
      },
    },
    {
      text: "六个月",
      value: () => {
        const date = new Date();
        date.setTime(date.getTime() + 3600 * 1000 * 24 * 30 * 6);
        return date;
      },
    },
    {
      text: "一年",
      value: () => {
        const date = new Date();
        date.setTime(date.getTime() + 3600 * 1000 * 24 * 30 * 12);
        return date;
      },
    },
    {
      text: "永久",
      value: () => {
        const date = new Date();
        date.setTime(date.getTime() + 3600 * 1000 * 24 * 30 * 12 * 100);
        return date;
      },
    },
  ];
}

/**
 * @description: 将转换为时分秒，可指定目标的格式
 * @param {*} seconds：秒数
 * @param {*} format：格式 默认为：HH:mm:ss
 * @return {*}
 */
export function formatSecondsToHMS(seconds, format = "HH:mm:ss") {
  if (seconds < 0) return false;
  const currentTime = moment.duration(seconds, "seconds");
  return moment({
    h: currentTime.hours(),
    m: currentTime.minutes(),
    s: currentTime.seconds(),
  }).format(format);
}

/**
 * @description: 时间转换
 * @param {*} value
 * @return {*}
 */
export function formatSeconds(value) {
  let result = parseInt(value);
  let h =
    Math.floor(result / 3600) < 10
      ? "0" + Math.floor(result / 3600)
      : Math.floor(result / 3600);
  let m =
    Math.floor((result / 60) % 60) < 10
      ? "0" + Math.floor((result / 60) % 60)
      : Math.floor((result / 60) % 60);
  let s =
    Math.floor(result % 60) < 10
      ? "0" + Math.floor(result % 60)
      : Math.floor(result % 60);
  result = `${h}:${m}:${s}`;
  return result;
}

/**
 * @description: 将4.12类型的转换为4时7秒
 * @param {*} value：需要转换数据
 * @param {*} h：小时格式
 * @param {*} m：分钟格式
 * @return {*} 4h7m
 */
export function convertTime(value, h = "时", m = "分") {
  var hours = Math.floor(value);
  var minutes = Math.round((value - hours) * 60);
  if (minutes === 60) {
    hours += 1;
    minutes = 0;
  }
  hours = hours < 10 ? "0" + hours : hours;
  minutes = minutes < 10 ? "0" + minutes : minutes;
  return `${hours}${h}${minutes}${m} `;
}

/**
 * @description: 将数组按照指定长度分割为二维数组
 * @param {*} array：原始数组
 * @param {*} num：每段的长度
 * @return {*}：二维数组 [[],[]]
 */
export function generateTwoDimensionalArray(array, num = 20) {
  let newArr = [];
  for (let i = 0; i < array.length; ) {
    newArr.push(array.slice(i, (i += num)));
  }
  return newArr;
}

/**
 * @description: 从数组中获取指定key的合计
 * @param {*} array：数据源
 * @param {*} key：指定的key
 * @param {*} format：是否对结果进行格式化
 * @return {*}：合计结果
 */
export function getTotalOfArray(array = [], key, format = false) {
  let total = array.reduce((acc, pre) => {
    acc += pre[key];
    return acc;
  }, 0);

  if (format) {
    total = Number(total)
      .toFixed(2)
      .replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
  }
  return total;
}

/**
 * @description: 用于给表格的数据做统计
 * @param {*} data：数据源
 * @param {*} columns：列  传summary-method的参数中的 {columns}
 * @param {*} exclude：需要排除的列的prop
 * @param {*} _exclude：仅提取这几列的prop
 * @param {*} isFormat：是否对数据进行格式化
 * @param {*} title：汇总栏的问题
 * @return {*} ['合计','xxx']
 */
export function formatStatisticsData({
  data,
  columns = [],
  exclude = [],
  _exclude = [],
  isFormat = false,
  title = "合计",
} = {}) {
  let keys = columns.map((item) => item.property);
  const length = columns.length;
  let arr = new Array(length);

  exclude.forEach((acc) => {
    const index = keys.findIndex((item) => item === acc);
    if (index >= 0) keys[index] = "";
  });

  if (_exclude.length > 0) {
    const indexs = [];
    exclude = [];
    _exclude.forEach((acc) => {
      const index = keys.findIndex((item) => item === acc);
      if (index >= 0) indexs.push({ value: index, key: acc });
    });

    const _arr = new Array(length);
    indexs.forEach((item) => {
      _arr[item.value] = item.key;
    });

    keys = _arr;
  }

  keys.forEach((item, index) => {
    if (item.length === 0) {
      arr[index] = "";
      return;
    }
    const sum = data.reduce((prev, curr) => {
      const value = Number(curr[item]);
      return !Number.isNaN(value) ? prev + value : prev;
    }, 0);

    arr[index] = isFormat ? formatMoney(sum) : sum;
  });
  arr[0] = title;

  return arr;
}

/**
 * @description: 校验控制是否存在，并返回权限参数的值
 * @param {*} auth：指定的权限串
 * @return {*}
 */
export function verifyAuth(auth) {
  if (!auth) return false;
  const store = userStore();
  const auths = [];
  store.authArr.forEach((item) => {
    const key = Object.keys(item);
    auths.push(key[0]);
  });

  return auths.includes(auth)
    ? store.authArr.find((item) => item[auth])[auth]
    : false;
}

/**
 * @description: 主要用户echart图片数据格式化，如在指定数据中仅提取指定字段的前20条数据，后面的为其他并计算其他总和
 * @param {*} all：数据源
 * @param {*} key：提取的key
 * @param {*} value：提取的值
 * @return {*}
 */
export function $formatechartData(all, key, value) {
  const arr = [];
  if (all.length < 20) {
    return all.map((item) => {
      return { name: item[key], value: item[value] };
    });
  }
  if (all.length > 20) {
    arr.push(
      ...all
        .slice(0, 20)
        .map((item) => ({ name: item[key], value: item[value] }))
    );
  }

  const endArr = all.slice(20);
  const enditemValue = endArr.reduce((pur, crr) => {
    return (pur += crr[value]);
  }, 0);
  const v = enditemValue.toFixed(2);
  arr.push({ name: "其他", value: +v });
  return arr;
}

/**
 * @description: 压缩图片信息
 * @param {*} image：图片文件
 * @param {*} backType：需要返回的类型，默认blob
 * @param {*} quality：压缩比例，默认0.8
 * @return {*}
 */
export function compressorImage(image, backType, quality) {
  return new Promise((resolve, reject) => {
    // eslint-disable-next-line no-new
    new Compressor(image, {
      quality: quality || 0.6,
      success(result) {
        const file = new File([result], image.name, { type: image.type });
        if (!backType || backType === "blob") {
          resolve(result);
        } else if (backType === "file") {
          resolve(file);
        } else {
          resolve(file);
        }
      },
      error(err) {
        reject(err);
      },
    });
  });
}

/**
 * @description: 导出一个生成UUID的函数
 * @return {*}
 */
export function generateUUID() {
  let UUID = uuidv4();
  return UUID;
}

/**
 * @description: 生成后一位编号
 * @param {*} currentId
 * @return {*}
 */
export function generateNextId(currentId) {
  if (!currentId) {
    return "A001";
  }

  // 查找数字部分的起始和结束索引
  const nonNumeric = /\D+/g; // 匹配非数字字符
  let match;
  let startIndex = 0;

  while ((match = nonNumeric.exec(currentId)) !== null) {
    startIndex = match.index + match[0].length;
  }

  // 获取数字部分
  const numberPart = currentId.slice(startIndex);

  // 如果没有找到数字部分（即整个id都是非数字字符）
  if (numberPart === "") {
    return "A001";
  }

  // 将数字部分转换为整数并加1
  const nextNumber = parseInt(numberPart, 10) + 1;

  // 保留非数字前缀并添加新数字
  const prefix = currentId.slice(0, startIndex);
  const nextId = `${prefix}${nextNumber
    .toString()
    .padStart(numberPart.length, "0")}`;

  return nextId;
}

/**
 * @description: 根据编码规则生成新的编码
 * @param {*} str
 * @return {*}
 */
export function incrementAlphanumericId(str) {
  if (!str) return "A001";

  str = str.trim();
  const lastChar = str.charAt(str.length - 1);
  const lastCharCode = lastChar.charCodeAt(0);

  // 检查最后一个字符是否是字母
  if (lastCharCode >= 65 && lastCharCode <= 90) {
    // A-Z
    // 如果最后一个字符是Z，则需要检查倒数第二个字符
    if (lastCharCode === 90) {
      // Z
      const secondLastChar = str.charAt(str.length - 2);
      const secondLastCharCode = secondLastChar.charCodeAt(0);

      // 如果倒数第二个字符是数字，递增它
      if (secondLastCharCode >= 48 && secondLastCharCode <= 57) {
        // 0-9
        const incrementedNum = String(secondLastCharCode - 48 + 1);
        return str.slice(0, -2) + incrementedNum + "A";
      }
      // 如果倒数第二个字符是字母，则替换Z为A，并递增该字母（如果可能）
      else if (secondLastCharCode >= 65 && secondLastCharCode <= 89) {
        // A-Y
        return (
          str.slice(0, -1) + String.fromCharCode(secondLastCharCode + 1) + "A"
        );
      }
      // 如果倒数第二个字符也是Z，则整个字符串无法递增，返回原字符串
      else if (secondLastCharCode === 90) {
        // Z
        return str;
      }
    }
    // 如果最后一个字符不是Z，则递增它
    else {
      return str.slice(0, -1) + String.fromCharCode(lastCharCode + 1);
    }
  }
  // 如果最后一个字符是数字，找到最后一个数字并递增它
  else if (lastCharCode >= 48 && lastCharCode <= 57) {
    // 0-9
    let numStr = "";
    let i = str.length - 1;
    // 找到最后一个连续的数字序列
    while (i >= 0 && str.charCodeAt(i) >= 48 && str.charCodeAt(i) <= 57) {
      numStr = str.charAt(i) + numStr;
      i--;
    }
    const num = parseInt(numStr, 10);
    const incrementedNum = (num + 1).toString().padStart(numStr.length, "0"); // 保持原数字的长度
    return str.slice(0, i + 1) + incrementedNum;
  }
  // 如果字符串末尾没有字母或数字，则添加A
  else {
    return str + "A";
  }
}

/**
 * @description: 格式化事件
 * @param(string): timeStr
 * @return {*}
 */
export function timeStringToDecimal(timeStr) {
  if (timeStr.includes(":")) {
    const [minutes, seconds] = timeStr.split(":").map(Number);
    return minutes + Number((seconds / 60).toFixed(2));
  } else if (timeStr.includes(".")) {
    return timeStr;
  } else if (!isNaN(Number(timeStr))) {
    return timeStr;
  } else {
    return 0;
  }
}

export function formatNumber(money, length = 2) {
  let result = Number(money)
    .toFixed(length)
    .replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
  result = result.replace(/\.0+$/, "");
  const _money = Number(money);
  return isNaN(_money) ? 0 : result;
}
